package com.reactim.message.example;

import com.reactim.message.compression.MessageCompressor;
import com.reactim.message.dto.BatchMessageResponse;
import com.reactim.message.dto.BatchSendMessageRequest;
import com.reactim.message.dto.SendMessageRequest;
import com.reactim.message.entity.Message;
import com.reactim.message.metrics.ProtobufPerformanceMetrics;
import com.reactim.message.service.BatchMessageService;
import com.reactim.protocol.MessageProto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 优化功能使用示例
 * 演示消息压缩、批处理和性能监控的使用
 */
@Slf4j
@Component
@ConditionalOnProperty(name = "reactim.example.enabled", havingValue = "true")
public class OptimizationExample implements CommandLineRunner {
    
    private final MessageCompressor messageCompressor;
    private final BatchMessageService batchMessageService;
    private final ProtobufPerformanceMetrics performanceMetrics;
    
    public OptimizationExample(MessageCompressor messageCompressor,
                              BatchMessageService batchMessageService,
                              ProtobufPerformanceMetrics performanceMetrics) {
        this.messageCompressor = messageCompressor;
        this.batchMessageService = batchMessageService;
        this.performanceMetrics = performanceMetrics;
    }
    
    @Override
    public void run(String... args) throws Exception {
        log.info("=== ReactIM 优化功能演示 ===");
        
        // 1. 演示消息压缩功能
        demonstrateMessageCompression();
        
        // 2. 演示批处理功能
        demonstrateBatchProcessing();
        
        // 3. 演示性能监控功能
        demonstratePerformanceMonitoring();
        
        log.info("=== 演示完成 ===");
    }
    
    /**
     * 演示消息压缩功能
     */
    private void demonstrateMessageCompression() {
        log.info("--- 消息压缩功能演示 ---");
        
        try {
            // 创建一个大消息用于压缩测试
            String largeContent = "这是一个用于测试压缩功能的长消息内容。".repeat(100);
            
            MessageProto.TextContent textContent = MessageProto.TextContent.newBuilder()
                    .setText(largeContent)
                    .build();
            
            MessageProto.MessageContent content = MessageProto.MessageContent.newBuilder()
                    .setText(textContent)
                    .build();
            
            MessageProto.Message largeMessage = MessageProto.Message.newBuilder()
                    .setMessageId("demo-large-message")
                    .setFromUserId(1L)
                    .setToUserId(2L)
                    .setMessageType(MessageProto.MessageType.TEXT)
                    .setContent(content)
                    .setTimestamp(System.currentTimeMillis())
                    .build();
            
            // 压缩消息
            MessageCompressor.CompressedMessage compressed = messageCompressor.compress(largeMessage);
            
            // 获取压缩统计
            MessageCompressor.CompressionStats stats = messageCompressor.getCompressionStats(compressed);
            
            log.info("压缩结果:");
            log.info("  - 是否压缩: {}", compressed.isCompressed());
            log.info("  - 原始大小: {} 字节", stats.getOriginalSize());
            log.info("  - 压缩后大小: {} 字节", stats.getCompressedSize());
            log.info("  - 压缩比: {:.2f}%", stats.getCompressionRatio() * 100);
            log.info("  - 节省空间: {:.2f}%", stats.getSpaceSavingPercentage());
            
            // 验证解压缩
            if (compressed.isCompressed()) {
                byte[] decompressed = messageCompressor.decompress(compressed);
                byte[] original = largeMessage.toByteArray();
                boolean isValid = Arrays.equals(original, decompressed);
                log.info("  - 解压缩验证: {}", isValid ? "成功" : "失败");
            }
            
        } catch (Exception e) {
            log.error("消息压缩演示失败", e);
        }
    }
    
    /**
     * 演示批处理功能
     */
    private void demonstrateBatchProcessing() {
        log.info("--- 批处理功能演示 ---");
        
        try {
            // 创建批量消息请求
            List<SendMessageRequest> messages = Arrays.asList(
                createSampleMessage(1L, 2L, "批处理消息 1"),
                createSampleMessage(1L, 3L, "批处理消息 2"),
                createSampleMessage(1L, 4L, "批处理消息 3")
            );
            
            BatchSendMessageRequest batchRequest = new BatchSendMessageRequest();
            batchRequest.setMessages(messages);
            
            // 配置批处理选项
            BatchSendMessageRequest.BatchOptions options = new BatchSendMessageRequest.BatchOptions();
            options.setTransactional(false);  // 非事务模式
            options.setParallel(true);        // 并行处理
            options.setBatchSize(10);         // 批处理大小
            options.setTimeoutMs(10000L);     // 10秒超时
            options.setRetryCount(2);         // 重试2次
            batchRequest.setOptions(options);
            
            log.info("发送批处理请求: {} 条消息", messages.size());
            
            // 注意：这里只是演示，实际的BatchMessageService需要真实的MessageService依赖
            // 在真实环境中，这会发送消息并返回结果
            log.info("批处理配置:");
            log.info("  - 事务模式: {}", options.getTransactional());
            log.info("  - 并行处理: {}", options.getParallel());
            log.info("  - 批处理大小: {}", options.getBatchSize());
            log.info("  - 超时时间: {} ms", options.getTimeoutMs());
            log.info("  - 重试次数: {}", options.getRetryCount());
            
        } catch (Exception e) {
            log.error("批处理演示失败", e);
        }
    }
    
    /**
     * 演示性能监控功能
     */
    private void demonstratePerformanceMonitoring() {
        log.info("--- 性能监控功能演示 ---");
        
        try {
            // 模拟一些性能监控操作
            performanceMetrics.recordProtoToEntity("demo-conversion", () -> {
                // 模拟转换操作
                try {
                    Thread.sleep(10); // 模拟10ms的转换时间
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return "converted-result";
            });
            
            performanceMetrics.recordEntityToProto("demo-conversion", () -> {
                // 模拟转换操作
                try {
                    Thread.sleep(5); // 模拟5ms的转换时间
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return "proto-result";
            });
            
            // 记录消息大小统计
            performanceMetrics.recordMessageSize(2048, 1024); // 原始2KB，压缩后1KB
            performanceMetrics.recordMessageSize(4096, 1536); // 原始4KB，压缩后1.5KB
            
            // 获取性能报告
            ProtobufPerformanceMetrics.PerformanceReport report = performanceMetrics.getPerformanceReport();
            
            log.info("性能监控报告:");
            log.info("  - 处理消息总数: {}", report.getTotalMessages());
            log.info("  - 平均压缩比: {:.2f}%", report.getCompressionRatio() * 100);
            log.info("  - 平均原始大小: {:.2f} 字节", report.getAverageOriginalSize());
            log.info("  - 平均压缩大小: {:.2f} 字节", report.getAverageCompressedSize());
            log.info("  - 平均Proto转实体耗时: {:.2f} ms", report.getAverageProtoToEntityTime());
            log.info("  - 平均实体转Proto耗时: {:.2f} ms", report.getAverageEntityToProtoTime());
            
        } catch (Exception e) {
            log.error("性能监控演示失败", e);
        }
    }
    
    /**
     * 创建示例消息
     */
    private SendMessageRequest createSampleMessage(Long fromUserId, Long toUserId, String text) {
        SendMessageRequest request = new SendMessageRequest();
        request.setFromUserId(fromUserId);
        request.setToUserId(toUserId);
        request.setMessageType(Message.MessageType.TEXT);
        
        Message.MessageContent content = new Message.MessageContent();
        Message.TextContent textContent = new Message.TextContent();
        textContent.setText(text);
        content.setText(textContent);
        request.setContent(content);
        
        return request;
    }
}